package com.shhm.filter;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.benmanes.caffeine.cache.Cache;
import com.shhm.common.constants.HttpStatus;
import com.shhm.common.context.PermsContextHolder;
import com.shhm.common.dto.security.SecurityUser;
import com.shhm.common.entity.admin.SysRoleOperatePerms;
import com.shhm.common.entity.admin.SysUser;
import com.shhm.common.entity.system.SysPassAuth;
import com.shhm.common.mapper.SysRoleOperatePermsMapper;
import com.shhm.common.utils.*;
import io.lettuce.core.RedisCommandTimeoutException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.QueryTimeoutException;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author JackZ
 * @version 1.0
 * @description: 校验权限拦截器
 * @date 2025/8/1 下午5:12
 */
public class JwtAuthorizationFilter extends OncePerRequestFilter {
    private final RedisTemplate<String, String> redisTemplate;
    private final String[] pass_uri;
    private final SysRoleOperatePermsMapper roleOperatePermsMapper;
    private final Cache<String, List<SysRoleOperatePerms>> localPermissionsCache;
    private final Cache<String, List<SysPassAuth>> localSysPassAuthCache;
    @Value("${filter.openAuthorization}")
    private boolean openFilter;

    public JwtAuthorizationFilter(
            RedisTemplate<String, String> redisTemplate,
            String[] pass_uri,
            SysRoleOperatePermsMapper roleOperatePermsMapper,
            Cache<String, List<SysRoleOperatePerms>> localPermissionsCache,
            Cache<String, List<SysPassAuth>> localSysPassAuthCache
            ) {
        this.redisTemplate = redisTemplate;
        this.pass_uri = pass_uri;
        this.roleOperatePermsMapper=roleOperatePermsMapper;
        this.localPermissionsCache = localPermissionsCache;
        this.localSysPassAuthCache = localSysPassAuthCache;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        long start = System.currentTimeMillis();
        String uri = request.getRequestURI();
        for (String puri : pass_uri) {
            if (uri.contains(puri)){
                filterChain.doFilter(request, response);
                return;
            }
        }

//        提取数据
        String authHeader = request.getHeader("Authorization");
        if (Objects.isNull(authHeader) || !authHeader.startsWith("Bearer ")){
            ResponseUtil.sendErrorResponse(response, HttpStatus.FORBIDDEN, "您未执行登录操作");
        }
        String method = request.getMethod();
        String operateStr = getOperateStr(method);
        String token = authHeader.substring(7);
        List<String> roles = JwtUtil.getRoleFromToken(token);
        Integer uid = JwtUtil.getUIDFromToken(token);

        // 4. 检查权限
        SysRoleOperatePerms hasObj = SysPermsUtil.getOperatePermsObjectByRoles(roles, localPermissionsCache, redisTemplate, roleOperatePermsMapper, uri);
        if (Objects.isNull(hasObj)||!hasObj.getOperateStr().contains(operateStr)&&!hasObj.getOperateStr().equals("*")){
            ResponseUtil.sendErrorResponse(response, HttpStatus.FORBIDDEN, "您没有权限访问此资源");
            return;
        }

        PermsContextHolder.setPermissions(hasObj);

        filterChain.doFilter(request, response);
        System.out.println("JwtAuthorizationFilter.java-Line-88:执行时间为："+(System.currentTimeMillis()-start));
    }

//    获取对应的权限字符
    private String getOperateStr(String method){
        String res="";
        if (method.equals("GET")) res= "l";
        else if (method.equals("POST")) res= "a";
        else if (method.equals("DELETE")) res= "d";
        else if (method.equals("PUT")) res= "u";
        else res="unknown";
        return res;
    }
}
